/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.wadl;
import com.sun.javadoc.AnnotationDesc;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.RootDoc;
import com.sun.jersey.server.wadl.generators.resourcedoc.model.ClassDocType;
import com.sun.jersey.server.wadl.generators.resourcedoc.model.MethodDocType;
import com.sun.jersey.server.wadl.generators.resourcedoc.model.ResourceDocType;
import com.sun.jersey.wadl.resourcedoc.DocProcessorWrapper;
import com.sun.jersey.wadl.resourcedoc.ResourceDoclet;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
public class PentahoResourceDoclet extends ResourceDoclet {
private static final String OUTPUT_FILE_NAME = "wadlExtension.xml";
private static final String OUTPUT_PATH_PARAM = "-output";
private static final String SUPPORTED_TAG = "<supported>{0}</supported>";
private static final String DEPRECATED_TAG = "<deprecated>{0}</deprecated>";
private static final String DOCUMENTATION_TAG = "<documentation>{0}</documentation>";
private static final String PATH_ANNOTATION = "@javax.ws.rs.Path";
private static final String DEPRECATED_ANNOTATION = "@java.lang.Deprecated";
private static final String FACET_ANNOTATION = "@org.codehaus.enunciate.Facet";
private static final String UNSUPPORTED = "Unsupported";
private static boolean isDeprecated( AnnotationDesc[] annotationDescs ) {
for ( AnnotationDesc annotationDesc : annotationDescs ) {
if ( annotationDesc.toString().equals( DEPRECATED_ANNOTATION ) ) {
return true;
}
} return false;
}
private static boolean isSupported( AnnotationDesc[] annotationDescs ) {
for ( AnnotationDesc annotationDesc : annotationDescs ) {
if ( annotationDesc.toString().contains( FACET_ANNOTATION ) ) {
if ( annotationDesc.elementValues()[0].value().value().equals( UNSUPPORTED ) ) {
return false;
}
}
} return true;
}
private static String generateComment( MethodDoc methodDoc ) {
String documentation = methodDoc.getRawCommentText();
StringBuilder comment = new StringBuilder();
comment.append( MessageFormat.format( SUPPORTED_TAG, isSupported( methodDoc.annotations() ) ) )
.append( MessageFormat.format( DEPRECATED_TAG, isDeprecated( methodDoc.annotations() ) ) )
.append( MessageFormat.format( DOCUMENTATION_TAG, documentation ) );
return comment.toString();
}
public static boolean start( RootDoc root ) {
final String outputPath = getOutputPath( root.options() );
final DocProcessorWrapper docProcessor = new DocProcessorWrapper();
final ResourceDocType result = new ResourceDocType();
final ClassDoc[] classes = root.classes();
for ( ClassDoc classDoc : classes ) {
final ClassDocType classDocType = new ClassDocType();
AnnotationDesc[] annotationDescs = classDoc.annotations();
boolean toBeProcessed = false;
if ( annotationDescs != null ) {
for ( AnnotationDesc annotation : annotationDescs ) {
if ( annotation.toString().contains( PATH_ANNOTATION ) ) {
toBeProcessed = true;
}
}
if ( !toBeProcessed ) {
continue;
}
classDocType.setClassName( classDoc.qualifiedTypeName() );
classDocType.setCommentText( classDoc.commentText() );
docProcessor.processClassDoc( classDoc, classDocType );
for ( MethodDoc methodDoc : classDoc.methods() ) {
final MethodDocType methodDocType = new MethodDocType();
annotationDescs = methodDoc.annotations();
toBeProcessed = false;
if( annotationDescs != null ) {
for ( AnnotationDesc annotation : annotationDescs ) {
if ( annotation.toString().contains( PATH_ANNOTATION ) ) {
toBeProcessed = true;
}
}
if ( !toBeProcessed ) {
continue;
}
methodDocType.setMethodName( methodDoc.name() );
methodDocType.setCommentText( generateComment( methodDoc ) );
docProcessor.processMethodDoc( methodDoc, methodDocType );
classDocType.getMethodDocs().add( methodDocType );
}
}
} result.getDocs().add( classDocType );
}
try {
final Class<?>[] clazzes = { result.getClass() };
final JAXBContext c = JAXBContext.newInstance( clazzes );
final Marshaller m = c.createMarshaller();
m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, true );
final OutputStream out = new BufferedOutputStream( new FileOutputStream( outputPath ) );
final XMLSerializer serializer = getXMLSerializer( out );
m.marshal( result, serializer );
out.close();
} catch ( Exception e ) {
return false;
}
return true;
}
private static XMLSerializer getXMLSerializer( OutputStream os )
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
OutputFormat of = new OutputFormat();
of.setCDataElements( new String[] { "ns1^commentText", "ns2^commentText", "^commentText" } );
XMLSerializer serializer = new XMLSerializer( of );
serializer.setOutputByteStream( os );
return serializer;
}
private static String getOutputPath( String[][] optionsMap ) {
if ( optionsMap != null ) {
for ( int i = 0; i < optionsMap.length; i++ ) {
String[] option = optionsMap[i];
if ( option[0].equals( OUTPUT_PATH_PARAM ) ) {
return option[1];
}
}
}
return OUTPUT_FILE_NAME;
}
}